<template>
    <div class="home-box">
        <main class="home-main">
            <div class="white-box mb-10">
                <div class="flex items-center justify-between">
                    <HeadTitle class="mb--20" title="统计"> </HeadTitle>
                    <div class="flex w-400">
                        <el-date-picker
                            v-model="state.date"
                            :type="
                                ['daterange', 'monthrange', 'yearrange'][
                                    state.rangeType - 1
                                ]
                            "
                            size="small"
                            range-separator="至"
                            start-placeholder="开始日期"
                            end-placeholder="截止日期"
                            :clearable="false"
                            @change="onDateChange"
                        />
                        <el-select
                            v-model="state.rangeType"
                            class="w-100 ml-5"
                            size="small"
                            placeholder="范围类型"
                            @change="onRangeTypeChange"
                        >
                            <el-option
                                v-for="item in state.countRangeTypeList"
                                :key="item.memberKey"
                                :label="item.memberName"
                                :value="item.memberKey"
                            />
                        </el-select>
                    </div>
                </div>

                <div id="trade-order" class="w-100% h-300"></div>
            </div>
            <div class="flex justify-between">
                <div class="white-box w-39.5%">
                    <HeadTitle title="30天用户日活趋势"></HeadTitle>
                    <div id="user-activity" class="w-100% h-300"></div>
                </div>
                <div class="white-box w-59.5%">
                    <div class="flex items-center justify-between">
                        <HeadTitle title="订单数据"></HeadTitle>
                        <el-select
                            v-model="state.orderCountRangeType"
                            class="w-100 ml-5"
                            size="small"
                            placeholder="范围类型"
                            @change="updateOrderNumberAndAmountEchart"
                        >
                            <el-option
                                v-for="item in state.countRangeTypeList"
                                :key="item.memberKey"
                                :label="item.memberName"
                                :value="item.memberKey"
                            />
                        </el-select>
                    </div>

                    <div class="flex">
                        <!-- 订单数 -->
                        <div class="w-50%">
                            <div id="order-number" class="w-100% h-300"></div>
                            <p class="text-center">订单数</p>
                        </div>
                        <!-- 订单交易额 -->
                        <div class="w-50%">
                            <div id="order-amount" class="w-100% h-300"></div>
                            <p class="text-center">订单交易额</p>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        <aside class="home-aside">
            <div class="white-box">
                <HeadTitle
                    title="系统消息"
                    title-size="14px"
                    text="更多"
                    text-size="12px"
                    @click="toMessageList"
                ></HeadTitle>
                <div
                    class="aside-li"
                    v-for="item in state.messages"
                    :key="item.id"
                    @click="toMessageDetail(item.sid)"
                >
                    <div class="w-65% line-one">{{ item.title }}</div>
                    <div>
                        <el-badge
                            :is-dot="item.whetherRead === 0"
                            badge-class="dot"
                            >{{ splitDate(item.created) }}</el-badge
                        >
                    </div>
                </div>
            </div>
        </aside>
    </div>
</template>

<script setup>
import {
    inject,
    ref,
    onActivated,
    onMounted,
    reactive,
    nextTick,
    onBeforeUnmount,
} from "vue";
import { useRouter, onBeforeRouteLeave } from "vue-router";
import { useUserStore } from "@stores/user";
import HeadTitle from "@components/HeadTitle.vue";
import { getMessagesUnread } from "@/apis/message.js";
import { formatDate, fenToYuan } from "@/assets/common/utils.js";
import {
    getTradeTrend,
    getOrderTrend,
    getUserActivityTrend,
    getCurrentOrderCount,
} from "@/apis/count.js";

// echarts
import Echarts from "@common/echarts";
import EchartsLine from "@common/echarts-line";
import EchartsPie from "@common/echarts-pie";

import { useDictStore } from "@stores/dict.js";

const dictStore = useDictStore();
dictStore
    .getDictMembers("count_range_type")
    .then((res) => (state.countRangeTypeList = res));

const router = useRouter();
const userStore = useUserStore();
const $message = inject("$message");
const $axios = inject("$axios");
const shortcuts = {
    week: {
        text: "近一周",
        value: () => {
            const start = new Date();
            start.setDate(start.getDate() - 7);
            const end = new Date();
            return [formatDayStart(start), formatDayEnd(end)];
        },
    },
    month: {
        text: "近一个月",
        value: () => {
            const start = new Date();
            start.setMonth(start.getMonth() - 1);
            const end = new Date();
            return [formatMonthStart(start), formatMonthEnd(end)];
        },
    },
    year: {
        text: "近一年",
        value: () => {
            const start = new Date();
            start.setFullYear(start.getFullYear() - 1);
            const end = new Date();
            return [formatYearStart(start), formatYearEnd(end)];
        },
    },
};
const state = reactive({
    countRangeTypeList: [],
    messages: [],
    date: null,
    rangeType: 1,
    orderCountRangeType: 1,
});

onMounted(() => {
    state.date = shortcuts.week.value();
});

onActivated(() => {
    getMessages();
    // 交易额和订单量
    updateTradeAndOrderEchart();
    // 用户日活趋势
    updateUserActivityTrendEchart();
    // 当前阶段订单统计
    updateOrderNumberAndAmountEchart();
});

onBeforeUnmount(() => {
    disposeEchart(tradeAndOrderEchart);
    disposeEchart(userActivityTrendEchart);
    disposeEchart(orderNumberEchart);
    disposeEchart(orderAmountEchart);
});

const disposeEchart = (echart) => {
    echart && echart?.dispose();
    echart = null;
};

// 获取年的起始时间 2024-01-01 00:00:00
const formatYearStart = (date) => {
    date.setMonth(0);
    date = formatMonthStart(date);
    return formatDayStart(date);
};

// 获取月的起始时间 2024-08-01 00:00:00
const formatMonthStart = (date) => {
    date.setDate(1);
    return formatDayStart(date);
};

// 获取日的起始时间 2024-08-08 00:00:00
const formatDayStart = (date) => {
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    return date;
};

// 获取年的最后时间 2024-12-31 23:59:59
const formatYearEnd = (date) => {
    date.setMonth(11);
    date.setDate(31);
    return formatDayEnd(date);
};

// 获取月的最后时间 2024-01-31 23:59:59
const formatMonthEnd = (date) => {
    // 设置到下个月的第一天 再减一天
    date.setMonth(date.getMonth() + 1);
    date = formatMonthStart(date);
    date = new Date(date.getTime() - 3600 * 1000);
    return formatDayEnd(date);
};

// 获取日的最后时间 2024-01-01 23:59:59
const formatDayEnd = (date) => {
    date.setHours(23);
    date.setMinutes(59);
    date.setSeconds(59);
    return date;
};

const onDateChange = (e) => {
    const [start, end] = e;
    switch (state.rangeType) {
        case 1:
            state.date = [formatDayStart(start), formatDayEnd(end)];
            break;
        case 2:
            state.date = [formatMonthStart(start), formatMonthEnd(end)];
            break;
        case 3:
            state.date = [formatYearStart(start), formatYearEnd(end)];
            break;
    }
    updateTradeAndOrderEchart();
};

const onRangeTypeChange = (e) => {
    const type = ["week", "month", "year"][e - 1];
    state.date = shortcuts[type].value();
    updateTradeAndOrderEchart();
};

// 交易额与订单量趋势
let tradeAndOrderEchart;
let tradeData = [];
let orderData = [];

// 获取【交易额】趋势
const getTrade = async () => {
    const { date, rangeType } = state;
    const startTime = formatDate(date[0]);
    const endTime = formatDate(date[1]);
    const res = await getTradeTrend({ startTime, endTime, rangeType });
    if (res.data.code === 200) {
        tradeData = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
};

// 获取【订单量】趋势
const getOrder = async () => {
    const { date, rangeType } = state;
    const startTime = formatDate(date[0]);
    const endTime = formatDate(date[1]);
    const res = await getOrderTrend({ startTime, endTime, rangeType });
    if (res.data.code === 200) {
        orderData = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
};

// 初始化【交易额与订单量】趋势图表
const initTradeAndOrderEchart = () => {
    if (!tradeAndOrderEchart) {
        tradeAndOrderEchart = Echarts.init(
            document.getElementById("trade-order")
        );
    }

    tradeAndOrderEchart.setOption(
        EchartsLine(
            tradeData.map((item) => item.countDate),
            ["交易额", "订单量"],
            [
                {
                    name: "交易额",
                    type: "line",
                    // smooth: true,
                    areaStyle: {
                        color: new Echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            {
                                offset: 0,
                                color: "rgba(64, 158, 255,1)",
                            },
                            {
                                offset: 1,
                                color: "rgba(255,255,255,0.6)",
                            },
                        ]),
                    },
                    data: tradeData.map((item) => fenToYuan(item.countAmount)),
                },
                {
                    name: "订单量",
                    type: "line",
                    // smooth: true,
                    areaStyle: {
                        color: new Echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            {
                                offset: 0,
                                color: "rgba(255, 124, 74,1)",
                            },
                            {
                                offset: 1,
                                color: "rgba(255,255,255,0.6)",
                            },
                        ]),
                    },
                    data: orderData.map((item) => item.countNum),
                },
            ]
        )
    );
};

// 更新【交易额与订单量】趋势图表
const updateTradeAndOrderEchart = async () => {
    await Promise.allSettled([getTrade(), getOrder()]);
    initTradeAndOrderEchart();
};

// 日活用户趋势统计(近30天)
let userActivityTrendEchart;
let userActivityTrendData = [];

const getUserActivity = async () => {
    const res = await getUserActivityTrend();
    if (res.data.code === 200) {
        userActivityTrendData = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
};

// 初始化【日活用户】趋势图表
const initUserActivityTrendEchart = () => {
    if (!userActivityTrendEchart) {
        userActivityTrendEchart = Echarts.init(
            document.getElementById("user-activity")
        );
    }

    userActivityTrendEchart.setOption(
        EchartsLine(
            userActivityTrendData.map((item) => item.countDate),
            [],
            [
                {
                    name: "日活数",
                    type: "line",
                    // smooth: true,
                    data: userActivityTrendData.map((item) => item.countNum),
                },
            ]
        )
    );
};

// 更新【日活用户】趋势图表
const updateUserActivityTrendEchart = async () => {
    await getUserActivity();
    initUserActivityTrendEchart();
};

// 当前阶段订单统计数据
// 订单数
let orderNumberEchart;
// 订单交易额
let orderAmountEchart;
let orderCountData = {
    orderNum: "0",
    finishNum: "0",
    refundedNum: "0",
    pendingNum: "0",
    orderAmount: "0",
    finishAmount: "0",
    refundedAmount: "0",
    pendingAmount: "0",
};

const getOrderCount = async () => {
    const res = await getCurrentOrderCount({ type: state.orderCountRangeType });
    if (res.data.code === 200) {
        orderCountData = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
};

// 初始化订单数饼图
const initOrderNumberEchart = () => {
    if (!orderNumberEchart) {
        orderNumberEchart = Echarts.init(
            document.getElementById("order-number")
        );
    }
    orderNumberEchart.setOption(
        EchartsPie([
            {
                name: "订单数",
                type: "pie",
                radius: "55%",
                center: ["50%", "50%"],
                itemStyle: {
                    borderRadius: 8,
                },
                data: [
                    { value: orderCountData.finishNum, name: "已成交" },
                    {
                        value: orderCountData.refundedNum,
                        name: "已退款",
                        itemStyle: {
                            color: "#CFD3DC",
                        },
                    },
                    { value: orderCountData.pendingNum, name: "待结算" },
                ],
            },
        ])
    );
};

// 初始化订单交易额饼图
const initOrderAmountEchart = () => {
    if (!orderAmountEchart) {
        orderAmountEchart = Echarts.init(
            document.getElementById("order-amount")
        );
    }
    orderAmountEchart.setOption(
        EchartsPie([
            {
                name: "订单交易额",
                type: "pie",
                radius: "55%",
                center: ["50%", "50%"],
                itemStyle: {
                    borderRadius: 8,
                },
                data: [
                    {
                        value: fenToYuan(orderCountData.finishAmount),
                        name: "已成交",
                        // itemStyle: {
                        //     color: "#67C23A",
                        // },
                    },
                    {
                        value: fenToYuan(orderCountData.refundedAmount),
                        name: "已退款",
                        itemStyle: {
                            color: "#CFD3DC",
                        },
                    },
                    {
                        value: fenToYuan(orderCountData.pendingAmount),
                        name: "待结算",
                        // itemStyle: {
                        //     color: "#E6A23C",
                        // },
                    },
                ],
            },
        ])
    );
};

// 更新【当前阶段订单统计】饼图
const updateOrderNumberAndAmountEchart = async () => {
    await getOrderCount();
    initOrderNumberEchart();
    initOrderAmountEchart();
};

const getMessages = async () => {
    const res = await getMessagesUnread();
    if (res.data.code === 200) {
        state.messages = res.data.data.records;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
};

const splitDate = (time) => {
    const date = new Date(time);
    const year = date.getFullYear();
    const nowYear = new Date().getFullYear();
    const res = formatDate(time, "YYYY-MM-DD");
    if (year === nowYear) {
        return res;
    } else {
        return res;
    }
};

const toMessageList = () => {
    router.push({
        name: "UserMessageList",
    });
};

const toMessageDetail = (sid) => {
    sid &&
        router.push({
            name: "UserMessageDetail",
            query: {
                sid,
            },
        });
};
</script>

<script>
export default {
    name: "Home",
};
</script>

<style lang="less" scoped>
.home-box {
    display: flex;
}

.home-main {
    flex: 1;
    padding: 0 20px 0 0;
}

.home-aside {
    flex: none;
    width: 260px;
    .aside-li {
        height: 28px;
        font-size: 12px;
        cursor: pointer;
        color: #323233;
        display: flex;
        justify-content: space-between;
        align-items: center;
        &:hover {
            color: #4b93fa;
        }
        :deep(.dot) {
            width: 4px;
            height: 4px;
            right: 2px;
        }
    }
}
</style>
